<template>
  <div class="pf-flow-prop-task" id="js-properties-panel-custom">
    <pf-form :config="formConfig" :model="formData" @changeEvent="formChange">
      <template v-slot:assignee-slot>
        <i class="el-icon-user" @click="openDialog(true, 'assignee')"
      /></template>
      <template v-slot:candidateUsers-slot>
        <i class="el-icon-user" @click="openDialog(true, 'candidateUsers')"
      /></template>
      <template v-slot:candidateGroups-slot>
        <i class="el-icon-user" @click="openDialog(false, 'candidateGroups')"
      /></template>
    </pf-form>
    <UserListDialog
      :show="userDialog"
      :multi="userDialogMulti"
      :notNull="false"
      @confirm="closeDialogWithSave"
      @close="closeDialog"
    ></UserListDialog>
    <DeptListDialog
      :show="deptDialog"
      :notNull="false"
      :multi="true"
      @confirm="closeDialogWithSave"
      @close="closeDialog"
    ></DeptListDialog>
  </div>
</template>

<script lang="ts">
import { defineComponent, nextTick, onMounted, ref, Ref, toRefs, watch } from 'vue';
import {
  buildReceiveTaskInfo,
  buildScriptTaskInfo,
  buildTaskInfo,
  buildUserTaskInfo
} from '@/views/page-config/flow/custom-properties/form-data';
import { modeler, TaskName } from '@/views/page-config/flow/flow-modeler';
import { FormFieldModel, FormModel } from 'pf-component';

export default defineComponent({
  name: 'ElementTask',
  props: ['id', 'type'],
  setup(props) {
    const formData: Ref = ref({ _async: [] } as any);
    const formConfig: Ref<FormModel> = ref(buildTaskInfo());
    const id: Ref = toRefs(props).id;
    const type: Ref = toRefs(props).type;
    const messageIdMap = new Map();
    const showExclusive = (newV: string[]): boolean => {
      return (
        newV && newV.length > 0 && (newV.includes('asyncBefore') || newV.includes('asyncAfter'))
      );
    };
    const formChange = (newV: any, prop: string) => {
      /*if (prop === "scriptFormat" || prop === "script" || prop === "resource" || prop === "resultVariable") {
        updateElementTask(prop);
      } else */ if (prop === '_async') {
        const field = formConfig.value.fields.find((f: FormFieldModel) => f.prop === prop);
        if (showExclusive(newV)) {
          const o = field?.options?.find(o => o.key === 'exclusive');
          if (o) {
            o.disabled = false;
          }
        } else {
          const o = field?.options?.find(o => o.key === 'exclusive');
          if (o) {
            o.disabled = true;
          }
          formData.value[prop] = formData.value[prop]?.filter((v: string) => v !== 'exclusive');
        }
        const val = {
          asyncBefore: newV && newV.includes('asyncBefore'),
          asyncAfter: newV && newV.includes('asyncAfter'),
          exclusive: showExclusive(newV)
        };
        modeler.updateActiveElement({
          ...val
        });
      } else if (prop === 'scriptType') {
        if (newV === 'inline') {
          formConfig.value.setHidden('resource', true);
          formConfig.value.setHidden('script', false);
        } else if (newV === 'external') {
          formConfig.value.setHidden('resource', false);
          formConfig.value.setHidden('script', true);
        }
      } else {
        updateElementTask(prop);
      }
    };
    const resetTaskForm = (type: string) => {
      // TODO wangjie
      /*接收任务*/
      formData.value.messageId = modeler.getActiveElement().businessObject?.messageRef?.id || '-1';
      /*用户任务*/
      formData.value.assignee = modeler.getActiveElement().businessObject.assignee || '';
      formData.value.candidateUsers = modeler.getActiveElement().businessObject.candidateUsers;
      formData.value.candidateGroups = modeler.getActiveElement().businessObject.candidateGroups;
      formData.value.dueDate = modeler.getActiveElement().businessObject.dueDate || '';
      formData.value.followUpDate = modeler.getActiveElement().businessObject.followUpDate || '';
      formData.value.priority = modeler.getActiveElement().businessObject.priority || '';
      /*脚本任务*/
      formData.value.scriptFormat = modeler.getActiveElement().businessObject.scriptFormat || '';
      formData.value.script = modeler.getActiveElement().businessObject.script || '';
      formData.value.resource = modeler.getActiveElement().businessObject.resource || '';
      formData.value.resultVariable =
        modeler.getActiveElement().businessObject.resultVariable || '';
      formData.value.scriptType = 'external';
      if (formData.value.script) {
        formData.value.scriptType = 'inline';
      }
    };
    const updateElementTask = (key?: string) => {
      const taskAttr = Object.create(null);
      if (key === 'messageId') {
        /*接收任务*/
        const messageId = formData.value.messageId;
        if (messageId === '-1') {
          modeler.updateActiveElement({
            messageRef: null
          });
        } else {
          modeler.updateActiveElement({
            messageRef: messageIdMap.get(messageId)
          });
        }
        return;
      }
      if (key) {
        /*用户任务 + 脚本任务*/
        taskAttr[key] = formData.value[key] || null;
        modeler.updateActiveElement(taskAttr);
        return;
      }
      /*脚本任务*/
      taskAttr.scriptFormat = formData.value.scriptFormat || null;
      taskAttr.resultVariable = formData.value.resultVariable || null;
      if (formData.value.scriptType === 'inline') {
        taskAttr.script = formData.value.script || null;
        taskAttr.resource = null;
      } else {
        taskAttr.resource = formData.value.resource || null;
        taskAttr.script = null;
      }
      modeler.updateActiveElement(taskAttr);
    };
    const userDialog: Ref<boolean> = ref(false);
    const deptDialog: Ref<boolean> = ref(false);
    const userDialogMulti: Ref<boolean> = ref(false);
    let activeDialogName = '';
    const openDialog = (user: boolean, name: string) => {
      activeDialogName = name;
      userDialog.value = user;
      deptDialog.value = !user;
      userDialogMulti.value = name !== 'assignee';
    };
    const closeDialog = () => {
      userDialog.value = false;
      deptDialog.value = false;
    };
    const closeDialogWithSave = (res: any[]) => {
      closeDialog();
      let val = '';
      if (res && res.length) {
        if (activeDialogName === 'assignee') {
          val = res[0].userId;
        } else if (activeDialogName === 'candidateUsers') {
          val = res.map(v => v.userId).join();
        } else if (activeDialogName === 'candidateGroups') {
          val = res.map(v => v.deptId).join();
        }
      }
      formData.value[activeDialogName] = val;

      // TODO wangjie 触发不了formChange，只能手动更新
      updateElementTask(activeDialogName);
    };
    onMounted(() => {
      const bpmnRootElements: any[] = [];
      modeler
        .getModeler()
        .getDefinitions()
        .rootElements.filter((el: any) => el.$type === TaskName.message)
        .forEach((m: any) => {
          bpmnRootElements.push({ key: m.id, value: m.name });
          messageIdMap.set(m.id, m);
        });
      bpmnRootElements.push({ key: '-1', value: '无' }); // 添加一个空对象，保证可以取消原消息绑定
      formConfig.value.setOptions('messageId', bpmnRootElements);
    });
    watch(
      type,
      () => {
        if (type.value === TaskName.user) {
          formConfig.value = buildUserTaskInfo();
        } else if (type.value === TaskName.script) {
          formConfig.value = buildScriptTaskInfo();
        } else if (type.value === TaskName.receive) {
          formConfig.value = buildReceiveTaskInfo();
        } else {
          formConfig.value = buildTaskInfo();
        }
      },
      { immediate: true }
    );
    watch(
      id,
      () => {
        const asyncArr = [];

        if (modeler.getActiveElement().businessObject.asyncBefore) {
          asyncArr.push('asyncBefore');
        }
        if (modeler.getActiveElement().businessObject.asyncAfter) {
          asyncArr.push('asyncAfter');
        }
        if (modeler.getActiveElement().businessObject.exclusive) {
          asyncArr.push('exclusive');
        }
        formData.value._async = asyncArr;
        nextTick(() => {
          resetTaskForm(type.value);
        });
      },
      { immediate: true }
    );
    return {
      formConfig,
      formData,
      formChange,
      closeDialog,
      closeDialogWithSave,
      openDialog,
      userDialog,
      deptDialog,
      userDialogMulti
    };
  }
});
</script>
<style scoped lang="scss">
.#{$prefix} {
}
</style>
